package com.leantech.android.browser.dialog

import android.content.Context
import androidx.annotation.AttrRes
import androidx.annotation.IdRes
import androidx.annotation.StringRes
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
import com.leantech.android.browser.databinding.LayoutBottomSheetMenuBinding
import com.leantech.android.browser.utils.onThrottleClick
import com.qmuiteam.qmui.kotlin.dip
import com.qmuiteam.qmui.skin.QMUISkinManager
import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet
import com.shencoder.pagergridlayoutmanager.PagerGridLayoutManager
import com.shencoder.pagergridlayoutmanager.PagerGridLayoutManager.PagerChangedListener
import okhttp3.internal.toImmutableList

class MenuBottomSheet internal constructor(context: Context, builder: Builder) :
    QMUIBottomSheet(context) {
    private val columnCount = builder.columnCount
    private val rowCount = builder.rowCount
    private val userClickListener: UserClickListener? = builder.userClickListener
    private val menuSettingClickListener: MenuSettingClickListener? =
        builder.menuSettingClickListener

    private val binding: LayoutBottomSheetMenuBinding =
        LayoutBottomSheetMenuBinding.inflate(layoutInflater)

    private val menuAdapter = MenuAdapter(this, builder.menuItemListener)

    private val layoutManager: PagerGridLayoutManager
    private val menuItems = mutableListOf<MenuItem>()


    init {
        addContentView(binding.root)

        layoutManager = PagerGridLayoutManager(rowCount, columnCount)
        layoutManager.isHandlingSlidingConflictsEnabled = true
        layoutManager.maxScrollOnFlingDuration = 200
        layoutManager.setPagerChangedListener(object : PagerChangedListener {

            private var tabCount = 0

            override fun onPagerCountChanged(pagerCount: Int) {
                if (tabCount == pagerCount) return
                if (pagerCount <= 0) {
                    binding.tabLayout.removeAllTabs()
                    tabCount = 0
                } else if (pagerCount > tabCount) {//we need add tab.
                    val delta = pagerCount - tabCount
                    repeat(delta) {
                        binding.tabLayout.addTab(binding.tabLayout.newTab(), false)
                    }
                    tabCount = pagerCount
                } else { //we need remove tab
                    for (i in pagerCount until tabCount) {
                        binding.tabLayout.removeTabAt(i)
                    }

                    tabCount = pagerCount
                }

            }

            override fun onPagerIndexSelected(prePagerIndex: Int, currentPagerIndex: Int) {
                binding.tabLayout.getTabAt(currentPagerIndex)?.select()
                builder.onPageSelected(currentPagerIndex)
            }
        })


        binding.recyclerView.layoutManager = layoutManager
        binding.recyclerView.adapter = menuAdapter

        menuItems.addAll(builder.menuItems)


        binding.tabLayout.addOnTabSelectedListener(object : OnTabSelectedListener {
            override fun onTabSelected(tab: TabLayout.Tab) {
                binding.recyclerView.post {
                    layoutManager.smoothScrollToPagerIndex(tab.position)
                }
            }

            override fun onTabUnselected(tab: TabLayout.Tab) {

            }

            override fun onTabReselected(tab: TabLayout.Tab) {

            }
        })

        binding.btnShare.onThrottleClick {
            menuSettingClickListener?.onMenuShareClick(this)
        }

        binding.btnSetting.onThrottleClick {
            menuSettingClickListener?.onMenuSettingClick(this)
        }


        setSkinManager(QMUISkinManager.defaultInstance(context))
        setRadius(builder.radius)
        setFitNav(true)
        behavior.setAllowDrag(true)
    }

    fun enableMenuItem(@IdRes id: Int, enabled: Boolean) {
        val indexOfItem = menuItems.indexOfFirst {
            it.viewId == id && it.enabled != enabled
        }
        if (indexOfItem == -1) {
            return
        }

        val oldItem = menuItems[indexOfItem]
        val newItem = oldItem.copy(enabled = enabled)
        menuItems.removeAt(indexOfItem)
        menuItems.add(indexOfItem, newItem)
    }


    fun checkMenuItem(@IdRes id: Int, checked: Boolean) {
        val indexOfItem = menuItems.indexOfFirst {
            it.viewId == id && it.checked != checked
        }
        if (indexOfItem == -1) {
            return
        }

        val oldItem = menuItems[indexOfItem]
        val newItem = oldItem.copy(checked = checked)
        menuItems.removeAt(indexOfItem)
        menuItems.add(indexOfItem, newItem)
    }

    fun selectMenuItem(@IdRes id: Int, selected: Boolean) {
        val indexOfItem = menuItems.indexOfFirst {
            it.viewId == id && it.selected != selected
        }
        if (indexOfItem == -1) {
            return
        }

        val oldItem = menuItems[indexOfItem]
        val newItem = oldItem.copy(selected = selected)
        menuItems.removeAt(indexOfItem)
        menuItems.add(indexOfItem, newItem)
    }

    override fun show() {
        super.show()
        commitAdapter()
    }

    private fun commitAdapter() {
        binding.recyclerView.post {
            menuAdapter.submitList(menuItems.toImmutableList())
        }
    }

    fun selectPage(pageIndex: Int) {
        layoutManager.scrollToPagerIndex(pageIndex)
    }


    interface MenuItemListener {
        fun onMenuItemClick(dialog: MenuBottomSheet, menuItem: MenuItem, position: Int)

        fun onMenuItemCheckChanged(
            dialog: MenuBottomSheet, menuItem: MenuItem, position: Int, checked: Boolean
        )

    }

    interface UserClickListener {
        fun onMenuUserClick(dialog: MenuBottomSheet)

    }

    interface MenuSettingClickListener {
        fun onMenuSettingClick(dialog: MenuBottomSheet)

        fun onMenuShareClick(dialog: MenuBottomSheet)
    }

    data class MenuItem(
        val viewId: Int,
        @AttrRes val icon: Int,
        @StringRes val text: Int,
        val checkable: Boolean = false,
        var enabled: Boolean = true,
        @StringRes val textOn: Int = 0,
        var checked: Boolean = false,
        var selected: Boolean = false
    )

    class Builder(private val context: Context) {
        internal var columnCount = 5
        internal var rowCount = 2
        internal var radius: Int = context.dip(24)
        internal var menuItemListener: MenuItemListener? = null
        internal var userClickListener: UserClickListener? = null
        internal var menuSettingClickListener: MenuSettingClickListener? = null
        internal val menuItems = mutableListOf<MenuItem>()
        internal var onPageSelected: (Int) -> Unit = {}

        fun setColumnCount(columnCount: Int) = apply {
            this.columnCount = columnCount
        }

        fun setRowCount(rowCount: Int) = apply {
            this.rowCount = rowCount
        }

        fun setRadius(radiusInDp: Int) = apply {
            this.radius = radiusInDp
        }

        fun setMenuItemClickListener(listener: MenuItemListener?) = apply {
            this.menuItemListener = listener
        }

        fun setPageSelectListener(pageSelectedListener: (Int) -> Unit) = apply {
            this.onPageSelected = pageSelectedListener
        }


        fun setUserClickListener(listener: UserClickListener?) = apply {
            this.userClickListener = listener
        }

        fun setMenuSettingClickListener(listener: MenuSettingClickListener?) = apply {
            this.menuSettingClickListener = listener
        }

        fun addNormalMenuItem(
            viewId: Int, @StringRes textRes: Int, @AttrRes iconRes: Int, enabled: Boolean = true
        ) = apply {
            menuItems.add(
                MenuItem(
                    viewId = viewId, icon = iconRes, text = textRes, enabled = enabled
                )
            )
        }

        fun addToggleMenuItem(
            viewId: Int,
            @StringRes textRes: Int,
            @AttrRes iconRes: Int,
            checked: Boolean = false,
            enabled: Boolean = true
        ) = apply {
            menuItems.add(
                MenuItem(
                    viewId = viewId,
                    icon = iconRes,
                    text = textRes,
                    checkable = true,
                    enabled = enabled,
                    checked = checked,
                    textOn = textRes
                )
            )
        }

        fun addToggleMenuItem(
            viewId: Int,
            @StringRes textRes: Int,
            @AttrRes iconRes: Int,
            checked: Boolean = false,
            enabled: Boolean = true,
            @StringRes textOnRes: Int,
        ) = apply {
            menuItems.add(
                MenuItem(
                    viewId = viewId,
                    icon = iconRes,
                    text = textRes,
                    checkable = true,
                    enabled = enabled,
                    checked = checked,
                    textOn = textOnRes
                )
            )
        }

        fun build(): MenuBottomSheet {
            return MenuBottomSheet(context, this)
        }
    }

}